//
// @ut.cpp
// CL.EXE /O2 /D _UNICODE /D UNICODE ut.cpp
//

#include <atlbase.h>
CComModule _Module;
#include <atlwin.h>

#include <windows.h>
#include <tchar.h>


#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "atl")

// 全局变量
HINSTANCE 		g_hInstance;
LPCTSTR	  		g_lpszWindowClass = _T("UTBrowserClass");
BOOL 			g_fFullScreen = FALSE;
WINDOWPLACEMENT g_wpNormal, g_wpFullScreen;
int 			g_nScreenWidth, g_nScreenHeight;
CAxWindow 		g_WinContainer;

HHOOK 			g_HookHwnd = NULL ;

TCHAR			g_szURL[1024];
TCHAR			g_szPWD[6];

#define WM_USER_NAVIGATE WM_USER+10


LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
VOID EnterFullScreen(HWND);
VOID ExitFullScreen(HWND);

VOID DbgPrint(LPCTSTR strOutputString,...)
{
    TCHAR strBuffer[4096]={0};
    va_list vlArgs;
    va_start(vlArgs,strOutputString);
    _vsntprintf(strBuffer,sizeof(strBuffer)-1,strOutputString,vlArgs);
    va_end(vlArgs);
    OutputDebugString(strBuffer);
}

/*
 * 注册Windows窗口类
 */
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcx;

	wcx.cbSize = sizeof(WNDCLASSEX);

	wcx.cbSize=sizeof(wcx);
	wcx.style=CS_HREDRAW|CS_VREDRAW;
	wcx.lpfnWndProc=WndProc;
	wcx.cbClsExtra=0;
	wcx.cbWndExtra=0;
	wcx.hInstance=hInstance;
	wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
	wcx.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	wcx.lpszMenuName=NULL;
	wcx.lpszClassName=g_lpszWindowClass;
	wcx.hIconSm=LoadIcon(NULL,IDI_APPLICATION);

	return RegisterClassEx(&wcx);
}

/*
 * 创建实例和主窗口
 */
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd; 
	hWnd = CreateWindow(g_lpszWindowClass, _T("UTBrowser"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	  return NULL;
	g_hInstance = hInstance;
	ShowWindow(hWnd, 3);
	UpdateWindow(hWnd);
	
	EnterFullScreen(hWnd);

	return hWnd;
}

VOID NavigateUrl(LPCTSTR lpcszUrl)
{
	IWebBrowser2* iWebBrowser;
	VARIANT varUrl;
	CComBSTR cbUrl(lpcszUrl);
	
	g_WinContainer.QueryControl(__uuidof(IWebBrowser2),(void**)&iWebBrowser);
	
	VariantInit(&varUrl);
	varUrl.vt = VT_BSTR;
	varUrl.bstrVal = (BSTR)cbUrl;
	iWebBrowser->put_Silent(1);
	iWebBrowser-> Navigate2(&varUrl,0,0,0,0);
	VariantClear(&varUrl); 
	iWebBrowser->Release(); 
}

HWND InitWinContainer(HWND hWnd)
{
	RECT rc = {0, 0, g_nScreenWidth, g_nScreenHeight};
	
	HWND hWin = g_WinContainer.Create(hWnd, rc, 0,WS_CHILD |WS_VISIBLE);
	g_WinContainer.CreateControl(OLESTR("shell.Explorer.2"));
	
	PostMessage(hWnd, WM_USER_NAVIGATE, 0, 0);
	return hWin;
}


/*
 * 窗口全屏
 */
VOID EnterFullScreen(HWND hWnd)
{
	RECT rectWindow, rectClient, rectFullScreen;
	POINT pointUpLeft,pointDownRight;
	
	if (g_fFullScreen)
		return;
	
	// 保存当前窗口显示信息
	g_wpNormal.length=sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(hWnd,&g_wpNormal);
	
	g_fFullScreen = TRUE;
	
	//获取窗口和客户区大小
	GetWindowRect(hWnd,&rectWindow);
	GetClientRect(hWnd,&rectClient);
	pointUpLeft.x=rectClient.left;
	pointUpLeft.y=rectClient.top;
	pointDownRight.x=rectClient.right;
	pointDownRight.y=rectClient.bottom;
	ClientToScreen(hWnd,&pointUpLeft);
	ClientToScreen(hWnd,&pointDownRight);	
	
	//计算全屏时窗口位置
	rectFullScreen.left=rectWindow.left-pointUpLeft.x;
	rectFullScreen.top=rectWindow.top-pointUpLeft.y;
	rectFullScreen.right=g_nScreenWidth+rectWindow.right-pointDownRight.x;
	rectFullScreen.bottom=g_nScreenHeight+rectWindow.bottom-pointDownRight.y;

	//调用SetWindowPlacement实现全屏
	g_wpFullScreen.length=sizeof(WINDOWPLACEMENT);
	g_wpFullScreen.flags=0;
	g_wpFullScreen.showCmd=SW_SHOWNORMAL;
	g_wpFullScreen.rcNormalPosition=rectFullScreen;
	SetWindowPlacement(hWnd,&g_wpFullScreen);	
}

/*
 * 退出窗口全屏
 */
VOID ExitFullScreen(HWND hWnd)
{
	if (!g_fFullScreen)
		return;	
	g_fFullScreen = FALSE;
	SetWindowPlacement(hWnd,&g_wpNormal);
}

/*
 * 屏蔽 CTRL + ALT + DEL
 */
void DisableTaskMgr(BOOL fDisable)
{
	HKEY hKey;
	LPCTSTR data = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
	if (RegOpenKeyEx(HKEY_CURRENT_USER, data, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
		RegCreateKey(HKEY_CURRENT_USER, data, &hKey);
	
	DWORD v = (fDisable ? 1 : 0);
	RegSetValueEx(hKey, _T("DisableTaskMgr"), 0, REG_DWORD, (LPBYTE)&v, sizeof(v));
	
	RegCloseKey(hKey);
}	


/*
 * 处理命令行
 */
VOID ParseCmd() 
{
	LPWSTR *argv;
	int 	argc;
	
	argv = CommandLineToArgvW(GetCommandLineW(), &argc);
	if (NULL == argv)
		return;
	
	lstrcpyn(g_szURL, (argc >=2 ? argv[1] : _T("about:blank")), 1024);
	lstrcpyn(g_szPWD, (argc >=3 ? argv[2] : _T("313131")), 6);
	
	//DbgPrint(_T("URL:%s PWD:%s"), g_szURL, g_szPWD);
}

LRESULT CALLBACK MyHookFun(int nCode, WPARAM wParam, LPARAM lParam)
{
	PKBDLLHOOKSTRUCT pkbhs = (PKBDLLHOOKSTRUCT)lParam;
	BOOL fControl = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);

	switch (nCode)  
    {  
		case HC_ACTION:
			//Disable CTRL+ESC  
			if (pkbhs->vkCode == VK_ESCAPE && fControl)  
				return 1;
			
			//Disable ALT+TAB
			if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
				return 1;

			//Disable ALT+ESC
			if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
				return 1;

			//Disable ALT+F4
			if (pkbhs->vkCode == VK_F4 && pkbhs->flags & LLKHF_ALTDOWN)
				return 1;				
			
			// Disable Left and Right Win Key
			if (pkbhs->vkCode == VK_LWIN || pkbhs->vkCode == VK_RWIN)
				return 1;
			break;
		default:
			break;
	}
	
	return CallNextHookEx(g_HookHwnd, nCode, wParam, lParam);
}

/*
 * 主窗口消息回调过程主函数
 */
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{	
	case WM_DESTROY:
		DisableTaskMgr(FALSE);
		UnhookWindowsHookEx(g_HookHwnd);
		PostQuitMessage(0);
		break;
		
	case WM_CREATE:
		//窗口创建
		
		g_nScreenWidth=GetSystemMetrics(SM_CXSCREEN);
		g_nScreenHeight=GetSystemMetrics(SM_CYSCREEN);
		
		InitWinContainer(hWnd);
		DisableTaskMgr(TRUE);
		g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_hInstance, 0);
		break;
	case WM_USER_NAVIGATE:
		NavigateUrl(g_szURL);
		break;
		
	case WM_KEYDOWN:
		//按键消息，F1全屏
		switch(wParam)
		{	
		case 'Q':
		case 'q':
			if (GetKeyState(VK_CONTROL)<0 && GetKeyState(VK_SHIFT) <0 && GetKeyState(VK_MENU) < 0)
				g_fFullScreen ? ExitFullScreen(hWnd) : EnterFullScreen(hWnd);
			
			break;
		}
		
		break;
		
	case WM_GETMINMAXINFO://窗口最小最大信息，如果不处理，挡不住任务栏
	{
		if(!g_fFullScreen) 
			break;
		
		//处理全屏最大大小
		LPRECT rc = &g_wpFullScreen.rcNormalPosition;
		MINMAXINFO *pmmi=(MINMAXINFO *)lParam;
		pmmi->ptMaxPosition.x=rc->left;
		pmmi->ptMaxPosition.y=rc->top;
		pmmi->ptMaxSize.x = rc->right - rc->left;
		pmmi->ptMaxSize.y = rc->bottom - rc->top;
		pmmi->ptMaxTrackSize.x = rc->right - rc->left;
		pmmi->ptMaxTrackSize.y = rc->right - rc->left;
		
		return 0;		
	}
	}
	
	return(DefWindowProc(hWnd,uMsg,wParam,lParam));
}

/*
 * 主入口函数
 */
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	ParseCmd();
	
	MSG msg;	
	MyRegisterClass(hInstance);
	HWND hWnd = InitInstance (hInstance, nCmdShow);
	if (!hWnd)
		return 0;
	
	GUID guid; 
	HRESULT hRes = _Module.Init(NULL, hInstance, &guid);
	
	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) {
		if (msg.message == WM_KEYDOWN) {
			SendMessage(hWnd, msg.message, msg.wParam, msg.lParam);
		}
		
		TranslateMessage(&msg);
		DispatchMessage(&msg);		
	}
	
	return msg.wParam;
}

